#include "gtest/gtest.h"
#include "ResourceFactory.h"
#include "BaseResource.h"

USING_NS_B2D

class MyResource
	: public BaseResource
{
	B2D_RESOURCE
public:
	typedef DefaultResourceFactory<MyResource,MyResource> Factory;
	bool loaded;

public:
	MyResource(void) : loaded(false) { }
	size_t getSizeEstimate(void) const { return 0; }
	void load(const StreamPtr& stream) { loaded = true; }
};
B2D_RESOURCE_IMPL(MyResource, BaseResource)

TEST(test_resourcefactory, test_add_remove_find)
{
	MyResource::Factory f;
	ResourcePtr r0(new MyResource());
	ResourcePtr r1(new MyResource());
	r0->setName("0");
	r1->setName("1");

	size_t before = f.getResourceCount();

	f._addResourceToCache(r0);
	f._addResourceToCache(r1);
	size_t during = f.getResourceCount();

	auto r = f.findResource("1");
	bool r1_eq_r1 = (r == r1);

	f._removeResourceFromCache("0");
	f._removeResourceFromCache("1");
	size_t after = f.getResourceCount();

	EXPECT_EQ(0, before);
	EXPECT_EQ(2, during);
	EXPECT_EQ(true, r1_eq_r1);
	EXPECT_EQ(0, after);
}

TEST(test_resourcefactory, test_clearing)
{
	MyResource::Factory f;
	ResourcePtr r0(new MyResource());
	ResourcePtr r1(new MyResource());
	ResourcePtr r2(new MyResource());
	ResourcePtr r3(new MyResource());
	r0->setName("0");
	r1->setName("1");
	r2->setName("2");
	r3->setName("3");

	// Now there should be 4
	f._addResourceToCache(r0);
	f._addResourceToCache(r1);
	f._addResourceToCache(r2);
	f._addResourceToCache(r3);
	size_t after_insertion = f.getResourceCount();

	// Clear unreferenced (all still referenced)
	f._clearUnreferenced();
	size_t clear_unref_0 = f.getResourceCount();

	// Unref 2 of them && clear unref
	r0.reset();
	r2.reset();
	f._clearUnreferenced();
	size_t clear_unref_2 = f.getResourceCount();

	// Clear whole thing
	f._clearCache();
	size_t clear_cache = f.getResourceCount();

	EXPECT_EQ(4, after_insertion);
	EXPECT_EQ(4, clear_unref_0);
	EXPECT_EQ(2, clear_unref_2);
	EXPECT_EQ(0, clear_cache);
}


TEST(test_resourcefactory, test_empty_creation)
{
	MyResource::Factory f;

	// Start with one
	ResourcePtr r0(new MyResource());
	r0->setName("0");
	f._addResourceToCache(r0);

	// Create and insert
	auto r1 = f._createEmpty("1", true);
	size_t insert = f.getResourceCount();

	// Create and dont insert
	auto r2 = f._createEmpty("2", false);
	size_t no_insert = f.getResourceCount();

	EXPECT_EQ(2, insert);
	EXPECT_EQ(2, no_insert);
}